﻿#include<iostream>
#include<cstdio>
#include "public.h"
#include"CommonConnectionPool.h"

ConnectionPool* ConnectionPool::getConnectionPool() {
	static ConnectionPool pool;
	return &pool;
}

ConnectionPool::ConnectionPool()
{
	// 加载配置项
	if (!loadConfigFile())
	{
		return;
	}

	/*
	创建初始数量的连接
	*/

	for (int i = 0; i < _initSize; ++i)
	{
		Connection* p = new Connection();
		p->connect(_ip, _port, _username, _password, _dbname);
		_connectQue.push(p);
		++_connectionCnt;
	}

	// 启动一个新的线程作为连接的生产者
	thread produceConnTask(std::bind(&ConnectionPool::produceConnectionTask, this));
	produceConnTask.detach();
	// 启动一个新的定时线程，扫描超过
	thread scannerConnTask(std::bind(&ConnectionPool::scannerConnectionTask, this));
	scannerConnTask.detach();
}

bool ConnectionPool::loadConfigFile() {
	FILE* pf = fopen("mysql.ini", "r");
	if (pf == nullptr)
	{
		LOG("mysql.ini file is not exist!");
		return false;
	}
	while (!feof(pf))
	{
		char line[1024] = { 0 };
		fgets(line, 1024, pf);
		string str = line;
		int idx = str.find('=', 0);
		if (idx == -1)
		{
			continue;
		}
		int endidx = str.find("\n", idx);
		string key = str.substr(0, idx);
		string value = str.substr(idx + 1, endidx - idx - 1);

		if (key == "ip")
		{
			_ip = value;
		}
		else if (key == "port")
		{
			_port = atoi(value.c_str());
		}
		else if (key == "username")
		{
			_username = value;
		}
		else if (key == "password")
		{
			_password = value;
		}
		else if (key == "dbname")
		{
			_dbname = value;
		}
		else if (key == "initSize")
		{
			_initSize = atoi(value.c_str());
		}
		else if (key == "maxSize")
		{
			_maxSize = atoi(value.c_str());
		}
		else if (key == "maxIdleTime")
		{
			_maxIdleTime = atoi(value.c_str());
		}
		else if (key == "connectionTimeOut")
		{
			_connectionTimeout = atoi(value.c_str());
		}
	}
	return true;
}

shared_ptr<Connection> ConnectionPool::getConnection()
{
	unique_lock<mutex> lock(_queueMutex);
	while (_connectQue.empty())
	{
		auto status = cv.wait_for(lock, chrono::milliseconds(_connectionTimeout));
		if (status == cv_status::timeout)
		{
			if (_connectQue.empty())
			{
				LOG("获取空闲连接超时了，获取连接失败！");
				return nullptr;
			}
		}

	}
	shared_ptr<Connection> sp(_connectQue.front(),
		[&](Connection* pcon) {
			unique_lock<mutex> lock(_queueMutex);
			pcon->refreshAliveTime();
			_connectQue.push(pcon);
		});
	_connectQue.pop();
	cv.notify_all();
	return sp;
}

void ConnectionPool::produceConnectionTask()
{
	for (;;)
	{
		unique_lock<mutex> lock(_queueMutex);
		while (!_connectQue.empty())
		{
			cv.wait(lock);
		}
		if (_connectionCnt < _maxSize)
		{
			Connection* p = new Connection();
			p->connect(_ip, _port, _username, _password, _dbname);
			_connectQue.push(p);
			++_connectionCnt;
		}
		cv.notify_all();
	}
}

void ConnectionPool::scannerConnectionTask()
{
	for (;;)
	{
		this_thread::sleep_for(chrono::seconds(_maxIdleTime));

		unique_lock<mutex> lock(_queueMutex);
		while (_connectionCnt > _initSize)
		{
			Connection* p = _connectQue.front();
			if (p->getAliveeTime() >= (_maxIdleTime * 1000))
			{
				_connectQue.pop();
				delete p;
			}
			else
			{
				break;
			}
		}
	}
}